package com.jevons.muffin.util.json;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * GsonUtil 操作类
 * <p/>
 * create at:  2016/5/4
 */
public final class GsonUtil {

    private static Gson gson = null;

    static {
        if (gson == null) {
            gson = new Gson();
        }
    }

    /**
     * json转对象
     *
     * @param jsonStr
     * @param cl
     * @return
     */
    public static Object jsonToBean(String jsonStr, Class<?> cl) {
        Object obj = null;
        if (gson != null) {
            obj = gson.fromJson(jsonStr, cl);
        }
        return obj;
    }

    /**
     * objectToJson
     *
     * @param object 需要转换的对象
     * @return
     */
    public static String objectToJson(Object object) {
        String jsonStr = null;
        if (gson != null) {
            jsonStr = gson.toJson(object);
        }
        return jsonStr;
    }

    /**
     * 对象转换成json字符串（不将obj中的特殊符号进行unicode编码）
     *
     * @param obj 要转化的对象
     * @return String
     */
    public static String toJsonNoUnicode(Object obj) {
        Gson gson = new GsonBuilder().disableHtmlEscaping().create();
        return gson.toJson(obj);
    }

    /**
     * objectToJson(可指定转换类型)
     *
     * @param object 需要转换的对象
     * @param type   转换类型
     * @return
     */
    public static String objectToJson(Object object, Type type) {
        String jsonStr = null;
        if (gson != null) {
            jsonStr = gson.toJson(object, type);
        }
        return jsonStr;
    }

    /**
     * json数据转成list
     *
     * @param jsonStr json字符串
     * @return List<?>数据
     */
    public static List<?> jsonToList(String jsonStr) {
        List<?> objList = null;
        if (gson != null) {
            Type type = new TypeToken<List<?>>() {
            }.getType();
            objList = gson.fromJson(jsonStr, type);
        }
        return objList;
    }

    /**
     * json字符串转list（可指定转换类型
     *
     * @param jsonStr json字符串
     * @param type    转换类型
     * @return
     */
    public static List<?> jsonToList(String jsonStr, Type type) {
        List<?> objList = null;
        if (gson != null) {
            objList = gson.fromJson(jsonStr, type);
        }
        return objList;
    }

    /**
     * jsonToMap
     *
     * @param jsonStr json字符串
     * @return
     */
    public static Map<?, ?> jsonToMap(String jsonStr) {
        Map<?, ?> objMap = null;
        if (gson != null) {
            Type type = new TypeToken<Map<?, ?>>() {
            }.getType();
            objMap = gson.fromJson(jsonStr, type);
        }
        return objMap;
    }

    /**
     * jsonToMap
     *
     * @param jsonStr json字符串
     * @return
     */
    public static Set<?> jsonToSet(String jsonStr) {
        Set<?> objSet = null;
        if (gson != null) {
            Type type = new TypeToken<Set<?>>() {
            }.getType();
            objSet = gson.fromJson(jsonStr, type);
        }
        return objSet;
    }

    /**
     * 对象转json通过时间序列化
     *
     * @param object     被转换的对象
     * @param dateformat 时间格式
     * @return 序列化对象的时候带时间格式
     */
    public static String objectToJsonDateSerializer(Object object, final String dateformat) {
        String jsonStr = null;
        gson = new GsonBuilder()
                .registerTypeHierarchyAdapter(Date.class,
                        new JsonSerializer<Date>() {
                            public JsonElement serialize(Date src,
                                                         Type typeOfSrc,
                                                         JsonSerializationContext context) {
                                SimpleDateFormat format = new SimpleDateFormat(dateformat);
                                return new JsonPrimitive(format.format(src));
                            }
                        }).setDateFormat(dateformat).create();
        if (gson != null) {
            jsonStr = gson.toJson(object);
        }
        return jsonStr;
    }

    /**
     * json转javaBean-并通过时间序列化
     *
     * @param jsonStr json字符串
     * @param cl      json转换成的实体类
     * @param pattern 转换格式
     * @param <T>     实体类
     * @return 序列化字符串的时候带时间格式
     */
    @SuppressWarnings("unchecked")
    public static <T> T jsonToBeanDateSerializer(String jsonStr, Class<T> cl,
                                                 final String pattern) {
        Object obj = null;
        gson = new GsonBuilder()
                .registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
                    public Date deserialize(JsonElement json, Type typeOfT,
                                            JsonDeserializationContext context)
                            throws JsonParseException {
                        SimpleDateFormat format = new SimpleDateFormat(pattern);
                        String dateStr = json.getAsString();
                        try {
                            return format.parse(dateStr);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                        return null;
                    }
                }).setDateFormat(pattern).create();
        if (gson != null) {
            obj = gson.fromJson(jsonStr, cl);
        }
        return (T) obj;
    }

    /**
     * 通过键值对获取值
     *
     * @param jsonStr json字符串
     * @param key     键
     * @return 值
     */
    public static Object getJsonValue(String jsonStr, String key) {
        Object rulsObj = null;
        Map<?, ?> rulsMap = jsonToMap(jsonStr);
        if (rulsMap != null && rulsMap.size() > 0) {
            rulsObj = rulsMap.get(key);
        }
        return rulsObj;
    }
}

